1 module recaptcha; 2 3 import std.utf; 4 import std.string; 5 import std.exception; 6 import vibe.http.client; 7 import vibe.stream.operations; 8 9 const string API_URL = "http://www.google.com/recaptcha/api"; 10 const string API_SECURE_URL = "https://www.google.com/recaptcha/api"; 11 const string VERIFY_URL = "http://www.google.com/recaptcha/api/verify"; 12 13 /** 14 * An exception type to distinguish exceptions thrown by this module. 15 */ 16 class RecaptchaException : Exception { 17 this(string msg, string file = __FILE__, size_t line = __LINE__) pure{ 18 super(msg, file, line); 19 } 20 } 21 alias RecaptchaException RCX; 22 23 /** 24 * Generate HTML for reCAPTCHA 25 */ 26 string recaptchaHTML(string publicKey, bool useSSL = false){ 27 string html; 28 string server; 29 30 // Raise exception if publickey isn't present 31 enforceEx!RCX(publicKey, "Tried to use a null publicKey parameter."); 32 enforceEx!RCX(publicKey != "", "Tried to enter an empty publicKey parameter."); 33 34 if (useSSL == true) 35 server = API_SECURE_URL; 36 else 37 server = API_URL; 38 html = r"<script type='text/javascript' src='" ~ server ~ r"/challenge?k=" ~ publicKey ~ "'></script>"; 39 html ~= r"<noscript><iframe src='" ~ server ~ r"/noscript?k=" ~ publicKey ~ r"' height='300' width='500' frameborder='0'></iframe><br/>"; 40 html ~= r"<textarea name='recaptcha_challenge_field' rows='3' cols='40'></textarea>"; 41 html ~= r"<input type='hidden' name='recaptcha_response_field' value='manual_challenge'/>"; 42 html ~= r"</noscript>"; 43 return html; 44 } 45 46 /** 47 * Check whether the answers entered by the users are correct 48 */ 49 bool verifyRecaptcha(string privateKey, string ip, string challenge, string response) { 50 bool successful; 51 string[] apiResponse; 52 string error; 53 string query; 54 55 // Raise exceptions for missing parameters 56 enforceEx!RCX(privateKey, "Tried to use a null private key parameter."); 57 enforceEx!RCX(privateKey != "", "Tried to enter an empty privateKey parameter."); 58 enforceEx!RCX(ip, "Tried to use a null remote IP parameter."); 59 enforceEx!RCX(ip != "", "Tried to enter an empty remote IP parameter."); 60 enforceEx!RCX(challenge, "Tried to use a null challenge parameter."); 61 enforceEx!RCX(challenge != "", "Entered an empty challenge parameter."); 62 enforceEx!RCX(response, "Tried to use a null response parameter."); 63 enforceEx!RCX(response != "", "Entered an empty response parameter."); 64 65 successful = false; 66 67 requestHTTP(VERIFY_URL, 68 (scope req) { 69 string requestBody; 70 71 query = "privatekey="~privateKey~"&remoteip="~ip~"&challenge="~challenge~"&response="~response; 72 73 req.method = HTTPMethod.POST; 74 req.headers["User-agent"] = "reCAPTCHA Vibe.d"; 75 76 requestBody = query; 77 req.writeBody(cast(ubyte[]) toUTF8(requestBody), "application/x-www-form-urlencoded; charset=UTF-8"); 78 }, 79 80 (scope res) { 81 apiResponse = splitLines( res.bodyReader.readAllUTF8() ); 82 if ( cast(string) apiResponse[0] == cast(string) "true" ) 83 successful = true; 84 else 85 successful = false; 86 } 87 ); 88 89 return (successful); 90 } 91 92 /** 93 * Check error returned by Recaptcha 94 * 95 * Returns either "true" or an error message 96 */ 97 string testRecaptcha(string privateKey, string ip, string challenge, string response) { 98 bool successful; 99 string[] apiResponse; 100 string error; 101 string query; 102 103 // Raise exceptions for missing parameters 104 enforceEx!RCX(privateKey, "Tried to use a null private key parameter."); 105 enforceEx!RCX(privateKey != "", "Tried to enter an empty privateKey parameter."); 106 enforceEx!RCX(ip, "Tried to use a null remote IP parameter."); 107 enforceEx!RCX(ip != "", "Tried to enter an empty remote IP parameter."); 108 enforceEx!RCX(challenge, "Tried to use a null challenge parameter."); 109 enforceEx!RCX(challenge != "", "Entered an empty challenge parameter."); 110 enforceEx!RCX(response, "Tried to use a null response parameter."); 111 enforceEx!RCX(response != "", "Entered an empty response parameter."); 112 113 successful = false; 114 115 requestHTTP(VERIFY_URL, 116 (scope req) { 117 string requestBody; 118 119 query = "privatekey="~privateKey~"&remoteip="~ip~"&challenge="~challenge~"&response="~response; 120 121 req.method = HTTPMethod.POST; 122 req.headers["User-agent"] = "reCAPTCHA Vibe.d"; 123 124 requestBody = query; 125 req.writeBody(cast(ubyte[]) toUTF8(requestBody), "application/x-www-form-urlencoded; charset=UTF-8"); 126 }, 127 128 (scope res) { 129 apiResponse = splitLines( res.bodyReader.readAllUTF8() ); 130 if ( cast(string) apiResponse[0] == cast(string) "true" ) 131 successful = true; 132 else 133 successful = false; 134 } 135 ); 136 137 if(successful) 138 return apiResponse[0]; 139 else 140 return apiResponse[1]; 141 }